module pl0.grammar;

//****************************************************************************
//*       this module holds the grammar rules and the parsing function.      *
//****************************************************************************

import pegged.grammar;

// TODO: create grammar rules for pl0
mixin(grammar(`
Arithmetic:
    Term     < Factor (Add / Sub)*
    Add      < "+" Factor
    Sub      < "-" Factor
    Factor   < Primary (Mul / Div)*
    Mul      < "*" Primary
    Div      < "/" Primary
    Primary  < Parens / Neg / Number / Variable
    Parens   < "(" Term ")"
    Neg      < "-" Primary
    Number   < ~([0-9]+)
    Variable <- identifier
`));

mixin(grammar(`
pl0:
	Program          <  Block :'.'


	Block            <  :'begin' (FlowCommand / Command)+ :'end'

	FlowCommand      <  (While)

	While            <  :'while' IsExpression Block :';'

	Command          <  (Initialization / Assign) :';'


	Assign           <  Identifier :':=' Expression

	Initialization   <  :'var' (Identifier :',')* Identifier

	IsExpression     <  Expression Comparator Expression

	Comparator       <  LessThan / GreaterThan / Equals / NotEquals
	LessThan         <  '<'
	GreaterThan      <  '>'
	Equals           <  '='
	NotEquals        <  '!='

	Expression       <  (SingleExpression)* (Number / Identifier)
	SingleExpression <  (Number / Identifier) Operation
	Operation        <  Add / Subtract / Multiply / Divide
	Add              <  '+'
	Subtract         <  '-'
	Multiply         <  '*'
	Divide           <  '/'

	Number           <~ ([0-9]+)

	Identifier       <  [a-z]

`));

/**
 * the parsing function - currently doesn't take inputs but that's just for testing
 * @return {ParseTree} returns the parseTree of the input, parsed with the grammer defined in this file
 */
ParseTree parse() {
	// TODO: parse a string or file. maybe a string would be good, main can handle the file stuff.
	ParseTree parseTree2 = pl0(`
begin
var x, y;
while 1 > 0
begin
x := 3;
var f;
while 2 = 3
begin
y := 123;
end;
end;
end.
`);

	return parseTree2;
}
